package com.jwd.avmanager.server;

import com.jwd.avmanager.constant.Cmd;
import com.jwd.avmanager.entity.DecodePacket;
import com.jwd.avmanager.parse.ProtocolParser;
import com.jwd.avmanager.util.DebugLogger;
import com.jwd.avmanager.util.ResponseFactory;
import com.jwd.avmanager.util.ThreadPoolUtil;

import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
import io.netty.handler.timeout.IdleStateEvent;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.concurrent.ConcurrentHashMap;

/**
 * @ProjectName: avmanager
 * @Desc: 信令tcp处理类
 * @Author: david
 * @Date: 2022/2/21
 */
public class SignalServerHandler extends ChannelInboundHandlerAdapter {
    Logger logger = LoggerFactory.getLogger(ProtocolParser.class);

    static final ThreadPoolUtil loginGroup = new ThreadPoolUtil(Runtime.getRuntime().availableProcessors() + 2, Runtime.getRuntime().availableProcessors() + 2, "login");
    //    private final EventExecutorGroup executorGroup = new DefaultEventExecutorGroup(10);//执任务的线程池
    static final ThreadPoolUtil exitGroup = new ThreadPoolUtil(Runtime.getRuntime().availableProcessors() / 2, Runtime.getRuntime().availableProcessors() / 2, "exit");
//    static final EventExecutorGroup exitGroup = new DefaultEventExecutorGroup(2);//退出的线程池
    //TODO 发送了不合法消息的客户端，超过五次则断开，后续可以考虑黑名单
    private ConcurrentHashMap<ChannelHandlerContext, Integer> invalidClients;

    public SignalServerHandler() {
        invalidClients = new ConcurrentHashMap<>();
    }

    @Override
    public void channelActive(ChannelHandlerContext ctx) throws Exception {
        //有活跃的连接上来了
    }

    @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
        DebugLogger.info("收到一个包，开始解析" + msg);
        if (!(msg instanceof DecodePacket)) {
            return;
        }
        DecodePacket packet = (DecodePacket) msg;
        //开线程处理

//        DebugLogger.debug("整体的协议数据  ->" + Arrays.toString(packet.getBytes()));
        ctx.channel().eventLoop().execute(new ParseTask(packet, ctx));
    }

    @Override
    public void channelInactive(ChannelHandlerContext ctx) throws Exception {
        DebugLogger.info("channelInactive:-->"+ctx.name());
        exitGroup.execute(new CloseTask(ctx));
    }

    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
        DebugLogger.info("exceptionCaught---->"+cause.getMessage());
        if(!cause.getMessage().equals("Connection reset by peer")){
            DebugLogger.err(logger,"SignalServerHandler cause.getMessage().equals(Connection reset by peer)");
            cause.printStackTrace();
        }
        //TODO 清理缓存 关闭连接
        byte[] fileNamebyte = "EXCEPTION_RESPONSE_0068".getBytes("gb2312");
        ResponseFactory.ExceptionResponse(Cmd.CMD_OUT_EXCEPTION_RESPONSE,fileNamebyte,ctx, logger);
        ClientManager.getInstance().closeCtx(ctx);
        //修改状态
    }

    @Override
    public void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception {
        if (evt instanceof IdleStateEvent) {
            IdleStateEvent e = (IdleStateEvent) evt;
            switch (e.state()) {
                case READER_IDLE:
                    //TODO 需要做超时处理
                    DebugLogger.info("读取超时");
                    exitGroup.execute(new CloseTask(ctx));
                    break;
            }
        }
    }

    @Override
    public void channelUnregistered(ChannelHandlerContext ctx) throws Exception {
        super.channelUnregistered(ctx);
    }

    /**
     * 信令解析任务
     */
    public static class ParseTask implements Runnable {
        private DecodePacket packet;
        private ProtocolParser parser;

        public ParseTask(DecodePacket packet, ChannelHandlerContext handlerContext) {
            this.packet = packet;
            parser = new ProtocolParser(handlerContext);
        }

        public DecodePacket getPacket() {
            return packet;
        }

        @Override
        public void run() {
            parser.parseMessage(packet);
        }
    }

    private static class CloseTask implements Runnable {
        ChannelHandlerContext ctx;

        public  CloseTask(ChannelHandlerContext ctx) {
            this.ctx = ctx;
        }

        @Override
        public void run() {
            ClientManager.getInstance().closeCtx(ctx);
        }
    }

}
